package cc.siyecao.fastdfs.util;

import cc.siyecao.fastdfs.config.FastDfsConfig;
import cc.siyecao.fastdfs.extception.FastDfsException;

import java.nio.charset.Charset;
import java.security.NoSuchAlgorithmException;

import static cc.siyecao.fastdfs.model.StoreFile.SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR;
import static cc.siyecao.fastdfs.protocol.ProtocolConstants.FDFS_FILE_EXT_NAME_MAX_LEN;

public class FastDfsUtil {


    /**
     * generate slave filename
     *
     * @param masterFileName the master filename to generate the slave filename
     * @param prefixName     the prefix name to generate the slave filename
     * @param extName        the extension name of slave filename, null for same as the master extension name
     * @return slave filename string
     */
    public static String genSlaveFilename(String masterFileName, String prefixName, String extName) throws FastDfsException {
        String trueExtName;
        int dotIndex;

        if (masterFileName.length() < 28 + FDFS_FILE_EXT_NAME_MAX_LEN) {
            throw new FastDfsException( "master filename \"" + masterFileName + "\" is invalid" );
        }

        dotIndex = masterFileName.indexOf( '.', masterFileName.length() - (FDFS_FILE_EXT_NAME_MAX_LEN + 1) );
        if (extName != null) {
            if (extName.length() == 0) {
                trueExtName = "";
            } else if (extName.charAt( 0 ) == '.') {
                trueExtName = extName;
            } else {
                trueExtName = "." + extName;
            }
        } else {
            if (dotIndex < 0) {
                trueExtName = "";
            } else {
                trueExtName = masterFileName.substring( dotIndex );
            }
        }

        if (trueExtName.length() == 0 && prefixName.equals( "-m" )) {
            throw new FastDfsException( "prefixName \"" + prefixName + "\" is invalid" );
        }

        if (dotIndex < 0) {
            return masterFileName + prefixName + trueExtName;
        } else {
            return masterFileName.substring( 0, dotIndex ) + prefixName + trueExtName;
        }
    }

    /**
     * md5 function
     *
     * @param source the input buffer
     * @return md5 string
     */
    public static String md5(byte[] source) {
        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
        java.security.MessageDigest md = null;
        try {
            md = java.security.MessageDigest.getInstance( "MD5" );
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        md.update( source );
        byte tmp[] = md.digest();
        char str[] = new char[32];
        int k = 0;
        for (int i = 0; i < 16; i++) {
            str[k++] = hexDigits[tmp[i] >>> 4 & 0xf];
            str[k++] = hexDigits[tmp[i] & 0xf];
        }

        return new String( str );
    }

    /**
     * get token for file URL
     *
     * @param remoteFileName the filename return by FastDFS server
     * @param ts             unix timestamp, unit: second
     * @param secretKey      the secret key
     * @return token string
     */
    public static String getToken(String remoteFileName, int ts, String secretKey, Charset charset) {
        byte[] bsFilename = remoteFileName.getBytes( charset );
        byte[] bsKey = secretKey.getBytes( charset );
        byte[] bsTimestamp = (new Integer( ts )).toString().getBytes( charset );
        byte[] buff = new byte[bsFilename.length + bsKey.length + bsTimestamp.length];
        System.arraycopy( bsFilename, 0, buff, 0, bsFilename.length );
        System.arraycopy( bsKey, 0, buff, bsFilename.length, bsKey.length );
        System.arraycopy( bsTimestamp, 0, buff, bsFilename.length + bsKey.length, bsTimestamp.length );

        return md5( buff );
    }

    /**
     * 获取文件全路径
     *
     * @return
     */
    public static String getWebUrl(String groupName, String fileName) {
        String webUrl = FastDfsConfig.getProperty( "fdfs.webUrl", "" );
        String fileFullName = groupName.concat( SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR ).concat( fileName );
        boolean antiStealToken = Boolean.valueOf( FastDfsConfig.getProperty( "fdfs.antiStealToken" ) );
        if (antiStealToken) {
            String charset = FastDfsConfig.getProperty( "fdfs.charset", "UTF-8" );
            String secretKey = FastDfsConfig.getProperty( "fdfs.secretKey" );
            if (StringUtils.isEmpty( secretKey )) {
                throw new FastDfsException( "fdfs.secretKey is empty!" );
            }
            int ts = (int) (System.currentTimeMillis() / 1000);
            String token = FastDfsUtil.getToken( fileName, ts, secretKey, Charset.forName( charset ) );
            fileFullName += "?token=" + token + "&ts=" + ts;
        }
        if (webUrl.endsWith( "/" )) {
            webUrl = webUrl + fileFullName;
        } else {
            webUrl = webUrl + "/" + fileFullName;
        }
        return webUrl;
    }

}
